package com.nulldev.util.net.tcp.dynReader;

import java.io.IOException;
import java.net.Socket;
import java.net.SocketException;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.regex.Pattern;

import com.nulldev.util.java.DataSet;
import com.nulldev.util.java.JVMUtil;
import com.nulldev.util.java.Variables;
import com.nulldev.util.logging.Logger;
import com.nulldev.util.logging.LoggerFactory;
import com.nulldev.util.napi.nullAPI;
import com.nulldev.util.net.packets.ConnectionManager;
import com.nulldev.util.net.packets.NetInfoAdapter;
import com.nulldev.util.net.packets.NetPacket;
import com.nulldev.util.net.packets.PacketManager;
import com.nulldev.util.net.tcp.TCPCore;
import com.nulldev.util.net.tcp.fRetry;
import com.nulldev.util.net.tcp.client.TCPClient;
import com.nulldev.util.net.tcp.client.TCPClient.ClientConnection;
import com.nulldev.util.other.Timer;
import com.nulldev.util.threading.ThreadUtils;
import com.nulldev.util.threading.v3.ThreadDispatcher;

public class DTCPClient extends TCPClient {

	private final CopyOnWriteArrayList<DataSet<NetPacket, TCPCore>> packets = 
			new CopyOnWriteArrayList<DataSet<NetPacket, TCPCore>>();
	
	public DTCPClient(String category, String name) {
		super(category, name);
	}
	
	public DTCPClient(String category, String name, String host, int port) {
		super(category, name, host, port);
	}
	
	@Override
	public void receive(String event, String payload, byte[] bytes, long count, final long readTime) {
		final NetPacket packet = PacketManager.parsePacket(this, null, event, bytes);
		if (!packet.isGeneric()) {
			//JVMUtil.async_println(event);
			//packet.client(packet.getData(), event, NetInfoAdapter.create(this.getConnection()));
			this.packets.add(new DataSet<NetPacket, TCPCore>(packet, getConnection()));
		}
	}
	
	public boolean hasPackets() {
		return !this.packets.isEmpty();
	}
	
	public DataSet<NetPacket, TCPCore> readPacket() {
		try {
			return this.packets.remove(0);
		}catch (Exception e) {
			return new DataSet<NetPacket, TCPCore>(null, null);
		}
	}
	
	public int packets() {
		return this.packets.size();
	}
	
	public void processPacket(final DataSet<NetPacket, TCPCore> packet) {
		packet.getA().client(packet.getA().getData(), packet.getA().toString(), NetInfoAdapter.create(packet.getB()));
	}
	
	public DataSet<NetPacket, TCPCore> waitForPacket(final String id) {
		return this.waitForPacket(id, 1000);
	}
	
	public DataSet<NetPacket, TCPCore> waitForPacket(final String id, final int wait) {
		final Timer t = new Timer();
		t.start(ThreadDispatcher.instance().getExec());
		while (!t.hasReached(wait)) {
			if (this.hasPackets()) {
				break;
			}
		}
		t.stop();
		for (final DataSet<NetPacket, TCPCore> set : this.packets) {
			if (set.getA().getID().equals(id)) {
				return set;
			}
		}
		return null;
	}
}
